/*-------------------------------------------------------------------------
 - Copyright (c) 2024-2025 [XD-AMCC TEAM]
 - [XD-AMCC] is licensed under Mulan PSL v2.
 - You can use this software according to the terms and conditions of the Mulan PSL v2.
 - You may obtain a copy of Mulan PSL v2 at:
 -          http://license.coscl.org.cn/MulanPSL2
 - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 - OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 - TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 - See the Mulan PSL v2 for more details.
 ------------------------------------------------------------------------*/


/**
 * @file
 * @brief  Interface of class symbol table and sym-table builder.
 *
 * @author  WXQ#XDU
 * @date    2024.12
 */

#pragma once


#ifndef AMCC_SYMBOL_TABLE_H
#define AMCC_SYMBOL_TABLE_H

#include <stdlib.h>

#include "amcc_hashmap.h"
#include "tree.h"
#include "symentry.h"

AMCC_DECL_BEGIN


/**
 * @brief Class symbol-table for a specific scope.
 *
 * <br/>
 * In order to reflect the nesting relationship between scopes, and to
 * enable name lookup according to the "most-closely-nested" rule,
 * AMCC will construct a symbol-table tree, and each symbol-table
 * corresponds to a scope.
 *
 * <br/>
 * The top-most table in tree is used to record all global names, it
 * corresponds to the non-terminal "translationUnit" of AMC grammar.
 *
 * @attention  All attributes SHOULD be accessed using API below
 *             named as "symtable_*()".
 */
typedef struct symbol_table {

    /// Pointer to a parse tree node that this table is bound to.
    ///
    /// This node is a function name definition node, or
    ///   a compoundStatement node, or
    ///   the only one 'translationUnit' node.
    t_tree_ptr  ownerTreeNode;

    /// Total memory size of variables in this scope
    size_t      totalSizeOfVariables;

    /// Pointer to the parent table of the enclosing block(nearest outer scope).
    struct symbol_table * parent;

    /// Set of symbol entries declared directly in current scope.
    /// The type is an instance of map<name, t_symentry_ptr>.
    struct hash_map     * localNames;

    /// A compoundStatements, excluding function body, is an anonymous
    ///   scope, and there is no symbol-entry corresponding to it.
    /// So, we use the field 'blockTables' to represent all anonymous
    ///   scopes enclosed directly in current compoundStatement block.
    ///
    /// In this way,
    ///
    /// (1) they are only a part of children of this parent table,
    ///     while the other children are of nested functions, and
    ///     attached to the functions' symbol-entry in field 'localNames',
    ///
    /// (2) each such child table stores all names declared directly
    ///     in a specific enclosed(inner) block.
    ///
    /// The real type is list<t_symtable_ptr>.
    t_list  blockTables;

} t_symtable, * t_symtable_ptr;


// -----------------------------------------------------------------------
/// @name API of class symbol-table
/// @{


/**
 * @brief Destroy a symbol table and it's all sub-tables of enclosed scopes.
 * @param pThis pointer to a symbol table of a scope
 */
extern void symtable_destroy(t_symtable_ptr pThis);

/**
 * @brief Dump a symbol table into file.
 *
 * @param pThis pointer to a symbol table of a scope
 */
extern void symtable_dump(t_symtable_ptr pThis);

/**
 * @brief Get the count of symbol entries declared directly
 *        in the corresponding scope.
 *
 * @param pThis   pointer to this symbol table
 * @return count of symbol entries in the corresponding scope.
 */
extern int  symtable_get_count(t_symtable_ptr pThis);

/**
 * @brief Get the total memory size allocated to all variables
 *        in the corresponding scope.
 *
 * @param pThis   pointer to this symbol table
 * @return Total memory size of all variables defined
 *        in the corresponding scope.
 */
extern size_t  symtable_get_memsize(t_symtable_ptr pThis);


/**
 * @brief Find the definition of a name according to the
 *        "most-closely-nested" rule.
 *
 * @param pThis   pointer to a symbol table which is the start
 *                point(innermost) to search
 * @param idNode  pointer to a tree-node marked by an ID token,
 *                it's name is used as a key
 * @return Return the symbol entry representing the name definition
 *         if found, otherwise return null.
 */
extern struct symtable_entry* symtable_find (t_symtable_ptr pThis,
        t_tree_ptr idNode );

/**
 * @brief Find the definition of a name ONLY in the specified
 *        symbol table(scope).
 *
 * @param pThis   pointer to this symbol table
 * @param idNode  pointer to a tree-node with the ID token, it's name is used as a key
 * @return Return the symbol entry representing the name definition if found,
 *         otherwise return null.
 */
extern struct symtable_entry* symtable_find_local (t_symtable_ptr pThis,
        t_tree_ptr idNode);


/**
 * @brief Find the symbol entry of a name according to the
 *        "most-closely-nested" rule.
 *
 * @param pThis   pointer to a symbol table which is the start
 *                point(innermost) to search
 * @param name    an ID text
 * @return Return the symbol entry representing the name definition
 *         if found, otherwise return null.
 */
extern t_symentry_ptr symtable_find_name (t_symtable_ptr pThis, const char * name);

/// @}
// -----------------------------------------------------------------------


// -----------------------------------------------------------------------
/// @name API of class symbol-table-builder
/// @{

typedef struct symbol_table_builder t_symtable_builder;

/**
 * @brief Creates a new symbol-table builder.
 * @param root  pointer to a parse tree of input AMC program
 * @return Return a new builder.
 */
extern t_symtable_builder * symtable_builder_new (t_tree_ptr  root);

/**
 * @brief  Build all symbol tables as a tree for an AMC program.
 * @param pThis  pointer to the symbol-table builder
 * @return On success, return 0; On failure, return a negative number.
 */
extern int symtable_builder_run (t_symtable_builder * pThis);

/**
 * @brief Get the error numbers during building symbol tables.
 * @param pThis  pointer to the symbol-table builder
 * @return the error numbers during building symbol tables.
 */
extern int symtable_builder_errors (t_symtable_builder * pThis);

/**
 * @brief Get the symbol table and change ownership to caller.
 * @param pThis  pointer to the symbol-table builder
 * @return Return the table built by builder.
 *
 * @note After call this function, caller MUST destroy the table.
 */
extern t_symtable_ptr symtable_builder_GRAB (t_symtable_builder * pThis);

/**
 * @brief Destroy the builder and release all inner resource.
 * @param pThis   pointer to the symbol-table builder
 */
extern void symtable_builder_destroy (t_symtable_builder * pThis);

/// @}
// -----------------------------------------------------------------------


AMCC_DECL_END

#endif // #ifndef AMCC_SYMBOL_TABLE_H
